/* Copyright (C)
 * 2017 - Xianlee.Wu  xianleewu@163.com
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>

#define WPA_SUPPLICANT "wpa_supplicant"
#define DNSMASQ "dnsmasq"
#define HOSTAPD "hostapd"

#define DNSMASQ_CONFIG_FILE "/tmp/dnsmasq.conf"
#define HOSTAPD_CONFIG_FILE "/tmp/hostapd.conf"

#define WLAN_DEVICE_NAME    "wlan0"
#define ETH_DEVICE_NAME     "eth0"

#define MAX_CMD_LEN         128

static char SSID[33];
static char PASSWD[65];

int runapp(char *cmd)
{
    int ret;
    ret = system(cmd);
    return ret;
}

static int get_pid(char *name)
{
    char buf[256] = {0};
    char cmd[30] = {0};
    FILE* pFile = NULL;
    int  pid = 0;

    sprintf(cmd, "pidof %s", name);

    pFile = popen(cmd, "r");
    if (pFile != NULL)  {
        while (fgets(buf, sizeof(buf), pFile)) {
            pid = atoi(buf);
            break;
        }
        pclose(pFile);
    }
    return pid;
}

int write_accesspoint_config_file(const char* path, const char* name,
        const char* password)
{
    char temp_buf[MAX_CMD_LEN] = {0};
    FILE* fp;
    fp = fopen(path, "wt+");

    snprintf(temp_buf, MAX_CMD_LEN, "interface=%s\n", WLAN_DEVICE_NAME);

    if (fp != 0) {
        fputs(temp_buf, fp);
        fputs("driver=nl80211\n", fp);
        fputs("ssid=", fp);
        fputs(name, fp);
        fputs("\n", fp);
        fputs("channel=6\n", fp);
        fputs("hw_mode=g\n", fp);
        fputs("ieee80211n=1\n", fp);
        fputs("ht_capab=[SHORT-GI-20]\n", fp);
        fputs("ignore_broadcast_ssid=0\n", fp);
        fputs("auth_algs=1\n", fp);
        fputs("wpa=3\n", fp);
        fputs("wpa_passphrase=", fp);
        fputs(password, fp);
        fputs("\n", fp);
        fputs("wpa_key_mgmt=WPA-PSK\n", fp);
        fputs("wpa_pairwise=TKIP\n", fp);
        fputs("rsn_pairwise=CCMP", fp);

        fclose(fp);
        return 0;
    }
    return -1;
}

int write_dnsmasq_config_file(const char* path)
{
    char temp_buf[MAX_CMD_LEN] = {0};
    FILE* fp;
    fp = fopen(path, "wt+");

    snprintf(temp_buf, MAX_CMD_LEN, "interface=%s\n", WLAN_DEVICE_NAME);

    if (fp != 0) {
        fputs("# dnsmasq config file\n", fp);
        fputs("no-resolv\n", fp);
        fputs("# Interface to bind to\n", fp);
        fputs(temp_buf, fp);
        fputs("# Specify starting_range,end_range,lease_time\n", fp);
        fputs("dhcp-range=192.168.100.3,192.168.100.254,12h\n", fp);
        fputs("# dns addresses to send to the clients\n", fp);
        fputs("server=8.8.8.8\n", fp);
        fputs("server=8.8.4.4\n", fp);
        fclose(fp);

        return 0;
    }

    return -1;
}

int check_hostapd_state()
{
    int hostapd_pid = 0;
    hostapd_pid =get_pid(HOSTAPD);
    if(hostapd_pid > 0) {
        return 1;
    }
    return 0;
}

int wlan_accesspoint_start(const char* ssid, const char* password)
{
    char temp_buf[MAX_CMD_LEN] = {0};

    if(check_hostapd_state() == 1) {
        printf("wifi ap is already running\n");
        return 0;
    }

    write_accesspoint_config_file(HOSTAPD_CONFIG_FILE, ssid, password);
    write_dnsmasq_config_file(DNSMASQ_CONFIG_FILE);

    runapp("kill -15 $(pidof dnsmasq)");
    runapp("rfkill unblock wlan");
    runapp("ifconfig lo 127.0.0.1 netmask 255.255.255.0");
    memset(temp_buf, 0, MAX_CMD_LEN);
    snprintf(temp_buf, MAX_CMD_LEN, "ifconfig %s up", WLAN_DEVICE_NAME);
    runapp(temp_buf);
    memset(temp_buf, 0, MAX_CMD_LEN);
    snprintf(temp_buf, MAX_CMD_LEN, "ifconfig %s 192.168.100.1",
            WLAN_DEVICE_NAME);
    runapp(temp_buf);

    runapp("echo 1 > /proc/sys/net/ipv4/ip_forward");
    runapp("iptables --flush");
    runapp("iptables --table nat --flush");
    runapp("iptables --delete-chain");
    runapp("iptables --table nat --delete-chain");

    memset(temp_buf, 0, MAX_CMD_LEN);
    snprintf(temp_buf, MAX_CMD_LEN, "iptables --table nat --append POSTROUTING \
            --out-interface %s -j MASQUERADE", ETH_DEVICE_NAME);
    runapp(temp_buf);

    memset(temp_buf, 0, MAX_CMD_LEN);
    snprintf(temp_buf, MAX_CMD_LEN, "iptables --append FORWARD --in-interface \
            %s -j ACCEPT", WLAN_DEVICE_NAME);
    runapp(temp_buf);

    runapp("dnsmasq -C /tmp/dnsmasq.conf");
    if (access("/dev/null", F_OK) != 0)
        runapp("mknod -m 666 /dev/null c 1 3");
    runapp("hostapd /tmp/hostapd.conf &");
    return 1;
}

